package es.chaveweb.poZit.client.ui.widget;

import com.google.gwt.cell.client.ValueUpdater;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.HasAllMouseHandlers;
import com.google.gwt.event.dom.client.HasChangeHandlers;
import com.google.gwt.event.dom.client.MouseDownEvent;
import com.google.gwt.event.dom.client.MouseDownHandler;
import com.google.gwt.event.dom.client.MouseMoveEvent;
import com.google.gwt.event.dom.client.MouseMoveHandler;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseOutHandler;
import com.google.gwt.event.dom.client.MouseOverEvent;
import com.google.gwt.event.dom.client.MouseOverHandler;
import com.google.gwt.event.dom.client.MouseUpEvent;
import com.google.gwt.event.dom.client.MouseUpHandler;
import com.google.gwt.event.dom.client.MouseWheelEvent;
import com.google.gwt.event.dom.client.MouseWheelHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.cellview.client.CellWidget;
import com.google.gwt.user.client.ui.HasEnabled;
import com.google.gwt.user.client.ui.HasText;
import com.google.gwt.user.client.ui.TextArea;
import com.grupit.engine.util.FormatterLogger;

import es.chaveweb.poZit.client.mvp.widget.PoZit;
import es.chaveweb.poZit.client.mvp.widget.PoZitData;
import es.chaveweb.poZit.client.ui.cell.PoZitCell;
import es.chaveweb.poZit.client.ui.cell.PoZitCell.Color;

public class PoZitImpl extends CellWidget<PoZitData> implements PoZit, HasText, HasAllMouseHandlers, HasEnabled,
		HasChangeHandlers {

	private static FormatterLogger logger = FormatterLogger.getLogger(PoZitImpl.class);

	private Presenter presenter;
	private Boolean pendingEnabled;

	private TextArea textArea;

	private String pendingWidth;

	private String pendingHeight;

	public PoZitImpl() {
		this(Color.YELLOW);
	}

	public PoZitImpl(Color color) {
		super(new PoZitCell(color, null){

			@Override
			public void onMouseDown(com.google.gwt.cell.client.Cell.Context context, Element parent, PoZitData value,
					NativeEvent event, ValueUpdater<PoZitData> valueUpdater) {
				// Nada
				
			}

			@Override
			public void onMouseUp(com.google.gwt.cell.client.Cell.Context context, Element parent, PoZitData value,
					NativeEvent event, ValueUpdater<PoZitData> valueUpdater) {
				// Nada
				
			}

			@Override
			public void onMouseMove(com.google.gwt.cell.client.Cell.Context context, Element parent, PoZitData value,
					NativeEvent event, ValueUpdater<PoZitData> valueUpdater) {
				// Nada
				
			}
			
		});
		redraw();

		Element divContainer = getElement().getFirstChildElement();
		Element divContent = (Element) divContainer.getChild(PoZitCell.Template.PoZitElementIndex.CONTENT.getIndex());
		this.textArea = new TextArea(divContent) {

		};

	}

	@Override
	public void setPresenter(Presenter presenter) {
		this.presenter = presenter;
	}

	@Override
	public String getText() {
		return this.textArea.getText();
	}

	@Override
	public void setText(String text) {
		this.textArea.setText(text);
	}

	@Override
	public HandlerRegistration addMouseDownHandler(MouseDownHandler handler) {
		return addDomHandler(handler, MouseDownEvent.getType());
	}

	@Override
	public HandlerRegistration addMouseUpHandler(MouseUpHandler handler) {
		return addDomHandler(handler, MouseUpEvent.getType());
	}

	@Override
	public HandlerRegistration addMouseOutHandler(MouseOutHandler handler) {
		return addDomHandler(handler, MouseOutEvent.getType());
	}

	@Override
	public HandlerRegistration addMouseOverHandler(MouseOverHandler handler) {
		return addDomHandler(handler, MouseOverEvent.getType());
	}

	@Override
	public HandlerRegistration addMouseMoveHandler(MouseMoveHandler handler) {
		return addDomHandler(handler, MouseMoveEvent.getType());
	}

	@Override
	public HandlerRegistration addMouseWheelHandler(MouseWheelHandler handler) {
		return addDomHandler(handler, MouseWheelEvent.getType());
	}

	@Override
	public boolean isEnabled() {
		return this.textArea.isEnabled();
	}

	@Override
	public void setEnabled(boolean enabled) {
		boolean isAttached = this.textArea.isAttached();

		if (isAttached) {
			this.textArea.setEnabled(enabled);
		} else {
			this.pendingEnabled = Boolean.valueOf(enabled);
		}
	}

	@Override
	protected void onAttach() {
		super.onAttach();

		if (this.pendingEnabled != null) {
			this.textArea.setEnabled(pendingEnabled);
			this.pendingEnabled = null;
		}

		if (this.pendingWidth != null) {
			this.setWidth(pendingWidth);
			this.pendingWidth = null;
		}

		if (this.pendingHeight != null) {
			this.setHeight(pendingHeight);
			this.pendingHeight = null;
		}
	}

	@Override
	public HandlerRegistration addChangeHandler(ChangeHandler handler) {
		return textArea.addChangeHandler(handler);
	}

	@Override
	public void setWidth(String width) {
		if (this.isAttached()) {
			int diff = getElement().getClientWidth() - textArea.getElement().getClientWidth();

			double widthPx = extractLengthValue(width);

			if (widthPx > 0) {
				textArea.setWidth((widthPx - diff) + "px");
			} else {
				super.setWidth(width);
			}
		} else {
			this.pendingWidth = width;
		}
	}

	@Override
	public void setHeight(String height) {
		if (this.isAttached()) {
			int diff = getElement().getClientWidth() - textArea.getElement().getClientWidth();
			double heightPx = extractLengthValue(height);

			if (heightPx > 0) {
				textArea.setHeight((heightPx - diff) + "px");
			} else {
				super.setHeight(height);
			}
		} else {
			this.pendingHeight = height;
		}
	}

	private native double extractLengthValue(String s) /*-{
		if (s == "auto" || s == "inherit" || s == "") {
			return 0;
		} else {
			// numberRegex is similar to java.lang.Number.floatRegex, but divides
			// the string into a leading numeric portion followed by an arbitrary
			// portion.
			var numberRegex = @com.google.gwt.user.client.ui.UIObject::numberRegex;
			if (!numberRegex) {
				numberRegex = @com.google.gwt.user.client.ui.UIObject::numberRegex = /^(\s*[+-]?((\d+\.?\d*)|(\.\d+))([eE][+-]?\d+)?)(.*)$/;
			}

			// Extract the leading numeric portion of s
			s = s.replace(numberRegex, "$1");
			return parseFloat(s);
		}
	}-*/;

}
